﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using GPSMap.Core.Misc.DAL;
using HTMapLib;
using MapControl;
using MapControl.Misc;
using MapControl.Misc.DAL;
using MapControl.Misc.GPSPoint;


namespace GPSMap
{
    public partial class ucGPSData : UserControl
    {
        public ucVectShapeMap _objMapControl;
        private AirPortRepository _airPortRespository;
        public ucGPSData(ucVectShapeMap mapControl, ComPort comPort)
        {
            
            InitializeComponent();
            try
            {
                _objMapControl = mapControl;
                _airPortRespository = new AirPortRepository(GeneralClass.appDBFile);
                GeneralClass.objPort.comPort_DataReceivedEventLog +=
                    new SerialDataReceivedEventHandler(comPort_DataReceivedLog);
                GeneralClass.objPort.comPort_SerialErrorReceivedEvent +=
                   new SerialErrorReceivedEventHandler(comPort_SerialErrorReceivedLog);
                GeneralClass.objPort.comPort_DataReceivedEventProcessor +=
                    new SerialDataReceivedEventHandler(comPort_DataReceivedEventProcessor);
                GeneralClass.IsViewLatestGPSPoint = false;
                _objMapControl.ucMap1.Map.Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        private void ucGPSData_Load(object sender, EventArgs e)
        {
            try
            {
                InitGPSGridViewControl();
                if (GeneralClass.objPort.IsOpen())
                {
                    btnOpenCOMPort.Text = "Đóng cổng COM";
                }
                else
                {
                    btnOpenCOMPort.Text = "Mở cổng COM";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        #region "GPSGridView Controls"
        //private ucGPSDataGridView _objUcGPSGridView;

        public void LoadAirport()
        {
            _objUcGPSGridView.LoadAirport();
        }


        /// <summary>
        /// 2014-11-06
        /// </summary>
        public void LoadCombobox_Planes()
        {
            _objUcGPSGridView.LoadCombobox_Planes();
            
        }

        private void InitGPSGridViewControl()
        {
            //_objUcGPSGridView = new ucGPSDataGridView(_objMapControl);
            _objUcGPSGridView.InitControl(_objMapControl, false);
            //_objUcGPSGridView.DataGridViewGPSData_MouseDoubleClickEvent += new System.Windows.Forms.MouseEventHandler(this.dataGridViewGPSData_MouseDoubleClick);
            //_objUcGPSGridView.DataGridViewGPSData_CurrentCellChangedEvent += new EventHandler(this.dataGridViewGPSData_CurrentCellChanged);
            _objUcGPSGridView.Dock = DockStyle.Fill;
            splitContainer2.Panel1.Controls.Add(_objUcGPSGridView);
        }

        //private void dataGridViewGPSData_MouseDoubleClick(object sender, MouseEventArgs e)
        //{
        //    try
        //    {
        //        if (_objUcGPSGridView.DataGridViewGPS.CurrentRow != null)
        //        {
        //            BaseGPSPoint objPoint = new GPSNormalPoint(GeneralClass.dbTestGPS.Rows[_objUcGPSGridView.DataGridViewGPS.CurrentCell.RowIndex]);
        //            _objMapControl.ucMap1.Map.ZoomTo(_objMapControl.ucMap1.Map.Zoom, objPoint.objGPSData.LonGPS,
        //                                             objPoint.objGPSData.LatGPS);
        //            _objMapControl.Refresh();

        //            Graphics g = _objMapControl.ucMap1.Map.CreateGraphics();
        //            //Tính lại tọa độ tâm center để vẽ object
        //            float centerX, centerY;
        //            centerX = centerY = 0;
        //            _objMapControl.ucMap1.Map.ConvertCoord(ref centerX, ref centerY, ref objPoint.objGPSData.LonGPS,
        //                                                   ref objPoint.objGPSData.LatGPS,
        //                                                   MapXLib.ConversionConstants.miMapToScreen);
        //            objPoint.CenterPoint = new PointF(centerX, centerY);
        //            objPoint.Draw(g, Color.Red);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
        //    }
        //}

        //private void dataGridViewGPSData_CurrentCellChanged(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        if (_objUcGPSGridView.DataGridViewGPS.CurrentRow != null)
        //        {
        //            int airport_id =
        //                int.Parse(
        //                    GeneralClass.dbTestGPS.Rows[_objUcGPSGridView.DataGridViewGPS.CurrentCell.RowIndex][
        //                        "airport_id"].ToString());
        //            Airport objAirport = _airPortRespository.GetAirportById(airport_id);

        //            BaseGPSPoint objPoint =
        //                new GPSNormalPoint(
        //                    GeneralClass.dbTestGPS.Rows[_objUcGPSGridView.DataGridViewGPS.CurrentCell.RowIndex]);
        //            toolStripStatusLabelDistance.Text = string.Format("Cách sân bay \"{0}\" khoảng {1} km",
        //                                                              objAirport.Airport_Name,
        //                                                              objPoint.objGPSData.Distance.ToString("#,##0"));
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
        //    }
        //}
        #endregion

        private string LogContent = "";
        private void UpdateLog(string log)
        {
            listBoxLog.BeginUpdate();
            log = string.Format("[{0}] {1}\n", listBoxLog.Items.Count + 1, log);
            listBoxLog.Items.Add(log);
            LogContent += log;
            listBoxLog.SelectedIndex = listBoxLog.Items.Count - 1;
            listBoxLog.EndUpdate();
        }

        delegate void SetLogCallback(string log);
        private void SetLog(string log)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.listBoxLog.InvokeRequired)
            {
                SetLogCallback d = new SetLogCallback(SetLog);
                this.Invoke(d, new object[] { log });
            }
            else
            {
                try
                {
                    UpdateLog(log);
                }
                catch (Exception ex)
                {
                    //throw ex;
                    UpdateLog(string.Format("[{0}] [Error Exception] {1}\r", DateTime.Now, ex.Message));
                }
                
            }
        }

        /// <summary>
        /// Hiển thị log ở ListBox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void comPort_DataReceivedLog(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                //Hiển thị log
                SetLog(GeneralClass.objPort.ListMessages[GeneralClass.objPort.ListMessages.Count - 1]);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        /// <summary>
        /// Hiển thị log ở ListBox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void comPort_SerialErrorReceivedLog(object sender, SerialErrorReceivedEventArgs e)
        {
            try
            {
                //Hiển thị log
                SetLog(GeneralClass.objPort.ListMessages[GeneralClass.objPort.ListMessages.Count - 1]);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        delegate void GPSDataProcessorCallback(string gpsdata);
        /// <summary>
        /// Xử lý dữ liệu nhận được từ cổng COM
        /// </summary>
        /// <param name="gpsdata"></param>
        private void GPSDataProcessor(string gpsdata)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (_objUcGPSGridView.DataGridViewGPS.InvokeRequired)
            {
                GPSDataProcessorCallback d = new GPSDataProcessorCallback(GPSDataProcessor);
                this.Invoke(d, new object[] { gpsdata });
            }
            else
            {
                GPSData gps;
                DataRow dr;
                try
                {
                    gps = new GPSData(gpsdata);
                    //========================================================
                    //Nếu các tọa độ hiện tại hiện tại chưa có thông tin máy bay mới
                    if (!GeneralClass.currGPSDataArr.ContainsKey(gps.Name))
                    {
                        //Cập nhật plane vào combobox
                        _objUcGPSGridView.UpdateCombobox_Planes(gps.Name);
                    }

                    double distance = _objMapControl.ucMap1.Map.Distance(GeneralClass.objCurrAirport.Longitude,
                                                                  GeneralClass.objCurrAirport.Latitude, gps.LonGPS,
                                                                  gps.LatGPS);
                    gps.Distance = (int)distance / 1000;
                    gps.Airport_Id = GeneralClass.objCurrAirport.Airport_Id;
                    //Lưu gps nhận được vào CSDL
                    GPSDataRepository.Save(gps);

                    //Tính khoảng cách để xem điểm mới nhận có hợp lệ về khoảng cách không
                    //DataRow lastGps = GeneralClass.dbTestGPS.Rows[GeneralClass.dbTestGPS.Rows.Count - 1];
                    //distance = _objMapControl.ucMap1.Map.Distance(double.Parse(lastGps[4].ToString()), double.Parse(lastGps[3].ToString()), gps.LonGPS, gps.LatGPS);
                    //Nếu khoảng cách điểm gps mới nhất so với khoảng cách điểm gps gần nhất 
                    //Khoảng cách chấp nhận nếu nằm trong (+-)500m
                    //if (distance > (gps.Speed / 3600)*1000 + 500)
                    //{
                    dr = GeneralClass.dbTestGPS.NewRow();
                    dr[0] = GeneralClass.dbTestGPS.Rows.Count + 1;
                    dr[1] = gps.Name;
                    dr[2] = gps.LatGPS;
                    dr[3] = gps.LonGPS;
                    dr[4] = gps.Alt;
                    dr[5] = gps.Speed;
                    dr[6] = gps.Angle;
                    dr[7] = gps.Distance;
                    dr[8] = gps.Airport_Id;
                    dr[9] = gps.Time;
                    dr[10] = gps.SatNum;
                    //========================================================
                    //2014-11-11
                    //Load tên máy bay
                    PlaneRepository objPlaneRepository = new PlaneRepository();
                    dr[11] = objPlaneRepository.GetPlaneName(gps.Name);
                    
                    GeneralClass.dbTestGPS.Rows.Add(dr);

                    //========================================================
                    //Cập nhật tọa độ hiện tại của các máy bay hiện có
                    GPSCurrentPoint currPlane = new GPSCurrentPoint(dr);
                    //Nếu các tọa độ hiện tại hiện tại chưa có thông tin máy bay mới
                    if (!GeneralClass.currGPSDataArr.ContainsKey(gps.Name))
                    {
                        //Thêm tọa độ hiện hành của máy bay mới
                        GeneralClass.currGPSDataArr.Add(gps.Name, currPlane);
                    }
                    else //Nếu máy bay đã xuất hiện thì cập nhật tọa độ mới nhất của máy bay đó
                    {
                        GeneralClass.currGPSDataArr[gps.Name] = currPlane;
                    }
                    
                    //========================================================
                    _objUcGPSGridView.UpdateDataGridView(GeneralClass.dbTestGPS);
                    _objUcGPSGridView.DataGridViewGPS.Rows[GeneralClass.dbTestGPS.Rows.Count - 1].Selected = true;
                    _objUcGPSGridView.DataGridViewGPS.FirstDisplayedScrollingRowIndex = GeneralClass.dbTestGPS.Rows.Count - 1;
                    _objUcGPSGridView.DataGridViewGPS.PerformLayout();

                }
                catch (Exception ex)
                {
                    UpdateLog(string.Format("[{0}] [Error Data] {1}: {2}\r", DateTime.Now, gpsdata, ex.Message));
                }
            }
        }
            /// <summary>
        /// Hiển thị log ở ListBox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void comPort_DataReceivedEventProcessor(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                //Hiển thị log
                GPSDataProcessor(GeneralClass.GPSData);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        private void OpenCOMPort()
        {
            //Mở kết nối
            try
            {
                //Kết nối về CSDL chuẩn
                string msg = GeneralClass.ConnectDatabase(GeneralClass.gpsDBFile);
                if (msg != "")
                {
                    MessageBox.Show(msg);
                    return;
                }
                btnOpenCOMPort.Text = "Đóng cổng COM";
                //btnOpenCOMPort.Text = "Mở cổng COM";
                GeneralClass.objPort.PortName = Properties.Settings.Default.PortName;
                GeneralClass.objPort.BaudRate = Properties.Settings.Default.BaudRate;
                GeneralClass.objPort.StopBits = Properties.Settings.Default.StopBits;
                GeneralClass.objPort.DataBits = Properties.Settings.Default.DataBits;
                GeneralClass.objPort.Parity = Properties.Settings.Default.Parity;
                //=====================================
                //Hiển thị dữ liệu buffer đã đọc ra log
                string log = string.Format("[{0}] [OpenPort]", DateTime.Now);
                SetLog(log);

                GeneralClass.objPort.comPortOpen();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Xảy ra lỗi sau khi kết nối:\n" + ex.Message, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                CloseCOMPort();
            }
        }

        private void CloseCOMPort()
        {
            //đóng kết nối
            try
            {
                btnOpenCOMPort.Text = "Mở cổng COM";
                //=====================================
                //Hiển thị dữ liệu buffer đã đọc ra log
                string log = string.Format("[{0}] [ClosePort]", DateTime.Now);
                SetLog(log);
                GeneralClass.objPort.comPortClose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Xảy ra lỗi sau khi kết nối:\n" + ex.Message, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public event EventHandler OpenCOMPort_ClickEvent;
        private void btnOpenCOMPort_Click(object sender, EventArgs e)
        {
            try
            {
                if (!GeneralClass.objPort.IsOpen())
                {
                    OpenCOMPort();
                }
                else
                {
                    GeneralClass.BackupDB(GeneralClass.gpsDBFile);
                    CloseCOMPort();
                }

                if (OpenCOMPort_ClickEvent != null)
                    OpenCOMPort_ClickEvent(sender, e);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }

        }

        private void btnSaveLog_Click(object sender, EventArgs e)
        {
            try
            {
                if (LogContent == "")
                {
                    MessageBox.Show("Không có nội dung log để lưu");
                    return;
                }

                SaveFileDialog saveFileDialog1 = new SaveFileDialog();
                saveFileDialog1.InitialDirectory = Convert.ToString(Environment.SpecialFolder.MyDocuments);
                saveFileDialog1.Filter = "Log (*.txt)|*.txt|All Files (*.*)|*.*";
                saveFileDialog1.FilterIndex = 1;

                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    using (StreamWriter sw = new StreamWriter(saveFileDialog1.FileName))
                    {
                        sw.Write(LogContent);
                    }
                } 
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        private void btnBackupFile_Click(object sender, EventArgs e)
        {
            try
            {
                string backupFile = GeneralClass.BackupDB(GeneralClass.gpsDBFile);
                if (backupFile != "")
                    MessageBox.Show("Sao lưu thành công ở đường dẫn " + backupFile);
                else
                    MessageBox.Show("Không có dữ liệu để sao lưu");
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
            }
        }

        

    }
}
